added samples
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2008 / CSEncryption / AsymmetricAlgorithmForm.cs
blob680214dfe96b2488093b320776e78ca17f80c388
1 /******************************** Module Header ********************************\
2 * Module Name: AsymmetricsAlgorithmForm.cs
3 * Project: CSEncryption
4 * Copyright (c) Microsoft Corporation.
5 *
6 * Asymmetric algorithms:
7 * It uses a public and private key pair to encrypt and decrypt data. The public
8 * key is made available to anyone and is used to encrypt data to be sent to
9 * the owner of the private key. The private key, as the name implies, is kept
10 * private. The private key is used to decrypt the data and will only work if
11 * the correct public key was used when encrypting the data. The private key is
12 * the only key that will allow data encrypted with the public key to be
13 * decrypted. The following public-key algorithms are available for use in
14 * the .NET Framework:
15 * RSA
16 * DSA
18 * This Form demonstrates how to use RSA algorithm to encrypt &
19 * decrypt data. I refer to some code from the book .NET Security and
20 * Cryptography.
22 * Code Logic:
23 * 1 Input the data into textbox so as to create message object
24 * 2 Click encrypt button
25 * 2.1 Serialize the message object to get plaintext data as byte array
26 * 2.2 Encrypt data by using RSACryptoServiceProvider object
27 * 2.3 Update UI display
28 * 3 Click decrypt button to decrypt) data
29 * 3.1 Create RSACryptoServiceProvider object. Initialize it with key, IV,etc
30 * 3.2 Decrypt ciphered data to get plain text
31 * 3.3 Update UI display
33 * This source is subject to the Microsoft Public License.
34 * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
35 * All other rights reserved.
37 * History:
38 * * 4/14/2009 09:00 AM Riquel Dong Created
39 \*******************************************************************************/
41 #region Using Directives
42 using System;
43 using System.Collections.Generic;
44 using System.ComponentModel;
45 using System.Data;
46 using System.Drawing;
47 using System.Linq;
48 using System.Text;
49 using System.Windows.Forms;
50 using System.Security.Cryptography;
51 using System.IO;
52 using System.Runtime.Serialization.Formatters.Binary;
53 #endregion
56 namespace CSEncryption
58 public partial class AsymmetricAlgorithmForm : Form
60 // Byte array to contain ciphered message
61 List<byte[]> cipherArray;
62 List<byte[]> recoveredArray;
64 public AsymmetricAlgorithmForm()
66 InitializeComponent();
67 cipherArray = new List<byte[]>();
68 recoveredArray = new List<byte[]>();
71 /// <summary>
72 /// Generate the public and private key for data encryption and decryption
73 /// </summary>
74 private void GenerateNewRSAParammeters()
76 try
78 // Create a RSA obj to perform asymmetric RSA algorithm
79 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
81 // Display publicprivate key in textbox control
82 tbxRSAParameters.Text = rsa.ToXmlString(true);
84 // Save the public and private keys to a XML file
85 using (StreamWriter sw = new StreamWriter("PublicPrivateKey.xml"))
87 sw.Write(tbxRSAParameters.Text);
90 // Save the public key to a XML file for encryption
91 using (StreamWriter sw = new StreamWriter("PublicOnlyKey.xml"))
93 sw.Write(rsa.ToXmlString(false));
96 // Update UI
97 ClearOutputFields();
98 cipherArray.Clear();
99 recoveredArray.Clear();
100 btnEncrypt.Enabled = true;
101 btnDecrypt.Enabled = false;
103 catch (Exception ex)
105 MessageBox.Show(ex.Message);
109 /// <summary>
110 /// Clear output value in textbox
111 /// </summary>
112 private void ClearOutputFields()
114 tbxIntegerPart.Text = string.Empty;
115 tbxMessagePart.Text = string.Empty;
116 tbxCiphertextasByteArray.Text = string.Empty;
117 tbxPlaintextasBytesArray.Text = string.Empty;
120 /// <summary>
121 /// Encrypt plaintext via public key.
122 /// This method is used just for demo. In real scenario we use symmetric
123 /// algorithm to encrypt data and use asymmetric algorithm to encrypt the
124 /// secret key used by symmetric algorithm
125 /// </summary>
126 private void btnEncrypt_Click(object sender, EventArgs e)
128 int number = 0;
129 if (string.IsNullOrEmpty(tbxInputMessage.Text) ||
130 !int.TryParse(tbxInputInterger.Text, out number))
132 MessageBox.Show("Invalid parameters!");
133 return;
136 // Clear old output in the textbox control
137 ClearOutputFields();
138 cipherArray.Clear();
139 Message msg = new Message();
140 msg.Num = number;
141 msg.MessageBody = tbxInputMessage.Text.Trim();
145 /////////////////////////////////////////////////////////////////
146 // Create a RSACryptoServiceProvider object and initialize it
147 // with a public key.
150 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
151 String publicOnlyKeyXml = string.Empty;
152 using (StreamReader sr = new StreamReader("PublicOnlyKey.xml"))
154 publicOnlyKeyXml = sr.ReadToEnd();
156 rsa.FromXmlString(publicOnlyKeyXml);
159 /////////////////////////////////////////////////////////////////
160 // Serialize message object to get plaintext as byte array.
163 BinaryFormatter bf = new BinaryFormatter();
164 byte[] plainBytes = null;
165 using (MemoryStream stream = new MemoryStream())
167 bf.Serialize(stream, msg);
168 plainBytes = stream.ToArray();
172 /////////////////////////////////////////////////////////////////
173 // Encrypt plaintext data via public key. Because there is the
174 // length limit in asymmetric algorithm, I split byte array to
175 // encrypt every small part byte array. In real scenario we
176 // should use symmetric algorithm to encrypt large quantities
177 // of data and use asymmetric algorithm to encrypt secret key
178 // used by symmetric algorithm.
181 int index = 0;
182 int length = 0;
183 if (plainBytes.Length > 80)
185 byte[] partPlainBytes;
186 byte[] cipherbytes;
187 while (plainBytes.Length - index > 0)
189 if (plainBytes.Length - index > 80)
191 partPlainBytes = new byte[80];
193 else
195 partPlainBytes = new byte[plainBytes.Length - index];
197 for (int i = 0; i < 80 && (index + i) < plainBytes.Length; i++)
198 partPlainBytes[i] = plainBytes[index + i];
199 cipherbytes = rsa.Encrypt(partPlainBytes, false);
200 length += cipherbytes.Length;
201 cipherArray.Add(cipherbytes);
202 index += 80;
207 /////////////////////////////////////////////////////////////////
208 // Display plaintext and ciphered data in UI.
211 byte[] cipheredPlaintext = new byte[length];
212 index = 0;
213 for (int i = 0; i < cipherArray.Count; i++)
215 for (int j = 0; j < cipherArray[i].Length; j++)
217 cipheredPlaintext[index + j] = cipherArray[i][j];
219 index += cipherArray[i].Length;
222 // Display ciphered message in textbox control as byte array
223 StringBuilder sb = new StringBuilder();
224 for (Int32 i = 0; i < cipheredPlaintext.Length; i++)
226 sb.Append(string.Format("{0:X2} ", cipheredPlaintext[i]));
228 tbxCiphertextasByteArray.Text = sb.ToString();
230 // Display plaintext in textbox control as byte array
231 sb = new StringBuilder();
232 for (Int32 i = 0; i < plainBytes.Length; i++)
234 sb.Append(string.Format("{0:X2} ", plainBytes[i]));
236 tbxPlaintextasBytesArray.Text = sb.ToString();
237 btnDecrypt.Enabled = true;
238 btnEncrypt.Enabled = false;
240 catch (Exception ex)
242 // Display the error information to user
243 MessageBox.Show(ex.Message);
247 /// <summary>
248 /// Decrypt the ciphered data via private key
249 /// </summary>
250 private void btnDecrypt_Click(object sender, EventArgs e)
254 /////////////////////////////////////////////////////////////////
255 // Create a RSACryptoServiceProvider object and initialize it
256 // with a public-private key pair.
259 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
260 String publicPrivateKeyXml = string.Empty;
261 using (StreamReader sr = new StreamReader("PublicPrivateKey.xml"))
263 publicPrivateKeyXml = sr.ReadToEnd();
265 rsa.FromXmlString(publicPrivateKeyXml);
266 recoveredArray.Clear();
269 /////////////////////////////////////////////////////////////////
270 // Get cipherd data as byte array and use the
271 // RSACryptoServiceProvider object to decrypt it.
274 int length = 0;
275 for (int i = 0; i < cipherArray.Count; i++)
277 byte[] partRecoveredPlainBytes = rsa.Decrypt(cipherArray[i], false);
278 recoveredArray.Add(partRecoveredPlainBytes);
279 length += partRecoveredPlainBytes.Length;
281 byte[] recoveredPlaintext = new byte[length];
282 int index = 0;
283 for (int i = 0; i < recoveredArray.Count; i++)
285 for (int j = 0; j < recoveredArray[i].Length; j++)
287 recoveredPlaintext[index + j] = recoveredArray[i][j];
289 index += recoveredArray[i].Length;
293 /////////////////////////////////////////////////////////////////
294 // Deserialize plaintext data to create message object and
295 // Display the data in UI.
298 BinaryFormatter bf = new BinaryFormatter();
299 using (MemoryStream stream = new MemoryStream())
301 stream.Write(recoveredPlaintext, 0, recoveredPlaintext.Length);
302 stream.Position = 0;
303 Message msgobj = (Message)bf.Deserialize(stream);
304 tbxIntegerPart.Text = msgobj.Num.ToString();
305 tbxMessagePart.Text = msgobj.MessageBody;
308 btnDecrypt.Enabled = false;
309 btnEncrypt.Enabled = true;
311 catch (Exception ex)
313 MessageBox.Show(ex.Message);
317 private void btnNewRSAParameters_Click(object sender, EventArgs e)
319 GenerateNewRSAParammeters();
322 private void tbxInputInterger_TextChanged(object sender, EventArgs e)
324 ClearOutputFields();
325 btnDecrypt.Enabled = false;
326 btnEncrypt.Enabled = true;
329 private void tbxInputMessage_TextChanged(object sender, EventArgs e)
331 ClearOutputFields();
332 btnDecrypt.Enabled = false;
333 btnEncrypt.Enabled = true;
336 private void AsymmetricAlgorithmForm_Load(object sender, EventArgs e)
338 GenerateNewRSAParammeters();
339 btnEncrypt.Enabled = true;
340 btnDecrypt.Enabled = false;